package com.mc.fastkit.view.shadow

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.graphics.drawable.InsetDrawable
import android.util.AttributeSet
import android.view.View
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.CornerSize
import com.google.android.material.shape.CornerTreatment
import com.google.android.material.shape.EdgeTreatment
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel
import com.mc.fastkit.R
import com.mc.fastkit.ext.getCornerSize
import com.mc.fastkit.view.StateType
import com.mc.fastkit.view.shape.RenderMode
import kotlin.math.atan2
import kotlin.math.max
import kotlin.math.sqrt

/**
 * ShadowViewDelegate
 * @author: MasterChan
 * @date: 2025-05-06 16:43
 */
@SuppressLint("RestrictedApi")
class ShadowViewDelegate(
    context: Context? = null,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : IShadowView {
    private lateinit var target: View

    override var stateType: StateType = StateType.NONE
    override var contentColor: Int = -1
    override var contentColorState: Int = -1
    override var contentColorDisable: Int = -1
    override var strokeColor: Int = -1
    override var strokeColorState: Int = -1
    override var strokeColorDisable: Int = -1
    override var strokeWidth: Float = 0f
    override var strokeWidthState: Float = 0f
    override var strokeWidthDisable: Float = 0f
    override var shadowEnable: Boolean = true
    override var shadowColour: Int = Color.BLACK
    override var shadowElevation: Float = 0f
    override var shadowOffsetY: Float = 0f
    override var shadowOffsetX: Float = 0f
    override var shadowFollowContent: Boolean = true
    override var autoInset: Boolean = false
    override var renderMode: Int = RenderMode.BACKGROUND

    override val topLeftCornerSize: Float
        get() = shapedDrawable.shapeAppearanceModel.topLeftCornerSize.getCornerSize(RectF())
    override val topRightCornerSize: Float
        get() = shapedDrawable.shapeAppearanceModel.topRightCornerSize.getCornerSize(RectF())
    override val bottomLeftCornerSize: Float
        get() = shapedDrawable.shapeAppearanceModel.bottomLeftCornerSize.getCornerSize(RectF())
    override val bottomRightCornerSize: Float
        get() = shapedDrawable.shapeAppearanceModel.bottomRightCornerSize.getCornerSize(RectF())
    override val topLeftCorner: CornerTreatment
        get() = shapedDrawable.shapeAppearanceModel.topLeftCorner
    override val topRightCorner: CornerTreatment
        get() = shapedDrawable.shapeAppearanceModel.topRightCorner
    override val bottomLeftCorner: CornerTreatment
        get() = shapedDrawable.shapeAppearanceModel.bottomLeftCorner
    override val bottomRightCorner: CornerTreatment
        get() = shapedDrawable.shapeAppearanceModel.bottomRightCorner
    override val leftEdge: EdgeTreatment
        get() = shapedDrawable.shapeAppearanceModel.leftEdge
    override val topEdge: EdgeTreatment
        get() = shapedDrawable.shapeAppearanceModel.topEdge
    override val rightEdge: EdgeTreatment
        get() = shapedDrawable.shapeAppearanceModel.rightEdge
    override val bottomEdge: EdgeTreatment
        get() = shapedDrawable.shapeAppearanceModel.bottomEdge

    override var contentColorDirty = true
    override var strokeColorDirty = true
    override val shapedBuilder = ShapeAppearanceModel().toBuilder()

    private val shapedDrawable = MaterialShapeDrawable()
    private var isSelected: Boolean? = null
    private var isDisable: Boolean? = null
    private var contentColorList: ColorStateList? = null
    private var strokeColorList: ColorStateList? = null

    init {
        if (context != null && attrs != null) {
            initAttrs(context, attrs, defStyleAttr, defStyleRes)
        }
    }

    private fun initAttrs(
        context: Context,
        attrs: AttributeSet,
        defStyleAttr: Int,
        defStyleRes: Int
    ) {
        val a = context.obtainStyledAttributes(
            attrs, R.styleable.ShadowView, defStyleAttr, defStyleRes
        )
        stateType = StateType.from(a.getInt(R.styleable.ShadowView_mc_stateType, -1))
        shadowEnable = a.getBoolean(R.styleable.ShadowView_mc_shadowEnable, true)
        shadowElevation = a.getDimension(R.styleable.ShadowView_mc_shadowElevation, 0f)
        shadowColour = a.getColor(R.styleable.ShadowView_mc_shadowColor, Color.BLACK)
        shadowOffsetX = a.getDimension(R.styleable.ShadowView_mc_shadowOffsetX, 0f)
        shadowOffsetY = a.getDimension(R.styleable.ShadowView_mc_shadowOffsetY, 0f)
        shadowFollowContent = a.getBoolean(R.styleable.ShadowView_mc_shadowFollowContent, true)
        autoInset = a.getBoolean(R.styleable.ShadowView_mc_autoInset, false)
        renderMode = a.getInteger(R.styleable.ShadowView_mc_renderMode, RenderMode.BACKGROUND)
        if (a.hasValue(R.styleable.ShadowView_mc_selected)) {
            isSelected = a.getBoolean(R.styleable.ShadowView_mc_selected, false)
        }
        if (a.hasValue(R.styleable.ShadowView_mc_disable)) {
            isDisable = a.getBoolean(R.styleable.ShadowView_mc_disable, false)
        }
        val cornerSize = a.getCornerSize(R.styleable.ShadowView_mc_cornerSize) { 0f }
        val cornerFamily = a.getInteger(R.styleable.ShadowView_mc_cornerFamily, 0)
        setTopLeftCorner(
            a.getInteger(R.styleable.ShadowView_mc_cornerFamilyTopLeft, cornerFamily),
            a.getCornerSize(R.styleable.ShadowView_mc_cornerSizeTopLeft, cornerSize)
        )
        setTopRightCorner(
            a.getInteger(R.styleable.ShadowView_mc_cornerFamilyTopRight, cornerFamily),
            a.getCornerSize(R.styleable.ShadowView_mc_cornerSizeTopRight, cornerSize)
        )
        setBottomLeftCorner(
            a.getInteger(R.styleable.ShadowView_mc_cornerFamilyBottomLeft, cornerFamily),
            a.getCornerSize(R.styleable.ShadowView_mc_cornerSizeBottomLeft, cornerSize)
        )
        setBottomRightCorner(
            a.getInteger(R.styleable.ShadowView_mc_cornerFamilyBottomRight, cornerFamily),
            a.getCornerSize(R.styleable.ShadowView_mc_cornerSizeBottomRight, cornerSize)
        )
        strokeWidth = a.getDimension(R.styleable.ShadowView_mc_strokeWidth, 0f)
        strokeColor = a.getColor(R.styleable.ShadowView_mc_strokeColor, Color.BLACK)
        strokeColorState = a.getColor(R.styleable.ShadowView_mc_strokeColor_state, strokeColor)
        strokeColorDisable = a.getColor(R.styleable.ShadowView_mc_strokeColor_disable, strokeColor)
        contentColor = a.getColor(R.styleable.ShadowView_mc_contentColor, Color.WHITE)
        contentColorState = a.getColor(R.styleable.ShadowView_mc_contentColor_state, contentColor)
        contentColorDisable = a.getColor(
            R.styleable.ShadowView_mc_contentColor_disable, contentColor
        )
        a.recycle()
    }

    override fun setup() = into(target)

    override fun into(target: View) {
        this.target = target
        if (contentColorDirty) {
            contentColorDirty = false
            contentColorList = createColorStateList(
                listOf(contentColor, contentColorState, contentColorDisable)
            )
        }
        if (strokeColorDirty) {
            strokeColorDirty = false
            strokeColorList = createColorStateList(
                listOf(strokeColor, strokeColorState, strokeColorDisable)
            )
        }

        shapedDrawable.initializeElevationOverlay(target.context)
        shapedDrawable.setShapeAppearanceModel(shapedBuilder.build())
        shapedDrawable.shadowCompatibilityMode = if (shadowEnable) {
            MaterialShapeDrawable.SHADOW_COMPAT_MODE_ALWAYS
        } else {
            MaterialShapeDrawable.SHADOW_COMPAT_MODE_NEVER
        }
        if (shapedDrawable.fillColor != contentColorList) {
            shapedDrawable.fillColor = contentColorList
        }
        if (shapedDrawable.strokeWidth != strokeWidth) {
            shapedDrawable.strokeWidth = strokeWidth
        }
        if (shapedDrawable.strokeColor != strokeColorList) {
            shapedDrawable.strokeColor = strokeColorList
        }
        if (shapedDrawable.elevation != shadowElevation) {
            shapedDrawable.elevation = shadowElevation
        }
        if (shadowFollowContent) {
            shapedDrawable.setUseTintColorForShadow(true)
            shapedDrawable.tintList = contentColorList
        } else {
            shapedDrawable.setShadowColor(shadowColour)
            shapedDrawable.setUseTintColorForShadow(false)
            shapedDrawable.tintList = null
        }
        setShadowOffset(shadowOffsetX, shadowOffsetY)
        val drawable: Drawable
        if (autoInset) {
            val left = max(shadowElevation - shadowOffsetX, 0f).toInt()
            val top = max(shadowElevation - shadowOffsetY, 0f).toInt()
            val right = max(shadowElevation + shadowOffsetX, 0f).toInt()
            val bottom = max(shadowElevation + shadowOffsetY, 0f).toInt()
            drawable = InsetDrawable(shapedDrawable, left, top, right, bottom)
        } else {
            drawable = shapedDrawable
        }
        if (renderMode == RenderMode.BACKGROUND) {
            this.target.background = drawable
        } else {
            this.target.foreground = drawable
        }
        if (isSelected != null) {
            this.target.isSelected = isSelected!!
            isSelected = null
        }
        if (isDisable != null) {
            this.target.isEnabled = !isDisable!!
            isDisable = null
        }
    }

    private fun createColorStateList(colors: List<Int>): ColorStateList {
        val normalColor = colors[0]
        val stateColor = colors[1]
        val disableColor = colors[2]
        return if (stateType != StateType.NONE) {
            val stateTypeState = stateType.androidState
            ColorStateList(
                arrayOf(
                    intArrayOf(android.R.attr.state_enabled, -stateTypeState),
                    intArrayOf(android.R.attr.state_enabled, stateTypeState),
                    intArrayOf(-android.R.attr.state_enabled)
                ),
                intArrayOf(normalColor, stateColor, disableColor)
            )
        } else {
            ColorStateList(
                arrayOf(
                    intArrayOf(android.R.attr.state_enabled),
                    intArrayOf(-android.R.attr.state_enabled)
                ),
                intArrayOf(normalColor, disableColor)
            )
        }
    }

    private fun setShadowOffset(y: Float, x: Float) {
        // 计算角度和距离（极坐标转换）
        val angleRad = atan2(y.toDouble(), x.toDouble())
        val angle = Math.toDegrees(angleRad).toInt()
        val distance = sqrt((x * x + y * y).toDouble())
        // 设置阴影方向和距离
        shapedDrawable.shadowCompatRotation = angle
        shapedDrawable.shadowVerticalOffset = distance.toInt()
    }
}